﻿using System;
using System.Runtime.InteropServices;


//alias Win32 types to Framework types
//IntPtr
using HANDLE = System.IntPtr;
using HDC = System.IntPtr;
using HBITMAP = System.IntPtr;
using LPVOID = System.IntPtr;
using HINSTANCE = System.IntPtr;

//String
using LPSTR = System.String;
using LPCSTR = System.String;
using LPWSTR = System.String;
using LPCWSTR = System.String;
using LPTSTR = System.String;
using LPCTSTR = System.String;

//UInt32
using DWORD = System.UInt32;
using UINT = System.UInt32;
using ULONG = System.UInt32;
using COLORREF = System.UInt32;

//Int32
using INT = System.Int32;
using LONG = System.Int32;
using BOOL = System.Int32;

//Other
using BYTE = System.Byte;
using SHORT = System.Int16;
using WORD = System.UInt16;
using CHAR = System.Char;
using FLOAT = System.Single;
using DOUBLE = System.Double;


namespace Gdi32
{
    public class Bitmaps
    {
        #region Bitmaps (資料結構)
        [StructLayout(LayoutKind.Sequential)]
        public struct BITMAPFILEHEADER
        {
            public ushort bfType;
            public int bfSize;
            public ushort bfReserved1;
            public ushort bfReserved2;
            public uint bfOffBits;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct BITMAPINFOHEADER
        {
            public uint biSize;
            public int biWidth;
            public int biHeight;
            public ushort biPlanes;
            public ushort biBitCount;
            public uint biCompression;
            public int biSizeImage;
            public int biXPelsPerMeter;
            public int biYPelsPerMeter;
            public uint biClrUsed;
            public uint biClrImportant;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct RGBQUAD
        {
            public byte Red;
            public byte Green;
            public byte Blue;
            public byte reserved;
        }


        [StructLayout(LayoutKind.Sequential)]
        public struct BITMAPINFO
        {
            public BITMAPINFOHEADER header;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
            public RGBQUAD[] bmiColors;
        }
        #endregion Bitmaps (資料結構)

        #region Bitmaps (函數)
        /*
//TODO: AlphaBlend 
/// <summary>
/// Displays a bitmap with transparent or semitransparent pixels. 
/// </summary>
/// <param name="hdcDest"></param>
/// <param name="nXOriginDest"></param>
/// <param name="nYOriginDest"></param>
/// <param name="nWidthDest"></param>
/// <param name="nHeightDest"></param>
/// <param name="hdcSrc"></param>
/// <param name="nXOriginSrc"></param>
/// <param name="nYOriginSrc"></param>
/// <param name="nWidthSrc"></param>
/// <param name="nHeightSrc"></param>
/// <param name="blendFunction"></param>
/// <returns></returns>
/// <remarks>System.Drawing.Graphics.DrawImage</remarks>
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
public static extern 
BOOL AlphaBlend(
HDC hdcDest, // handle to destination DC
int nXOriginDest, // x-coord of upper-left corner
int nYOriginDest, // y-coord of upper-left corner
int nWidthDest, // destination width
int nHeightDest, // destination height
HDC hdcSrc, // handle to source DC
int nXOriginSrc, // x-coord of upper-left corner
int nYOriginSrc, // y-coord of upper-left corner
int nWidthSrc, // source width
int nHeightSrc, // source height
BLENDFUNCTION blendFunction // alpha-blending function
);
*/

        /// <summary>
        /// BitBlt Performs a bit-block transfer. 
        /// </summary>
        /// <param name="hdcDest"></param>
        /// <param name="nXDest"></param>
        /// <param name="nYDest"></param>
        /// <param name="nWidth"></param>
        /// <param name="nHeight"></param>
        /// <param name="hdcSrc"></param>
        /// <param name="nXSrc"></param>
        /// <param name="nYSrc"></param>
        /// <param name="dwRop"></param>
        /// <returns></returns>
        /// <remarks>System.Drawing.Graphics.DrawImage</remarks>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        BOOL BitBlt(
        HDC hdcDest, // handle to destination DC
        int nXDest, // x-coord of destination upper-left corner
        int nYDest, // y-coord of destination upper-left corner
        int nWidth, // width of destination rectangle
        int nHeight, // height of destination rectangle
        HDC hdcSrc, // handle to source DC
        int nXSrc, // x-coordinate of source upper-left corner
        int nYSrc, // y-coordinate of source upper-left corner
        DWORD dwRop // raster operation code
        );


        /// <summary>
        /// Creates a bitmap. 
        /// </summary>
        /// <param name="nWidth"></param>
        /// <param name="nHeight"></param>
        /// <param name="cPlanes"></param>
        /// <param name="cBitsPerPel"></param>
        /// <param name="lpvBits"></param>
        /// <returns></returns>
        /// <remarks>System.Drawing.Bitmap constructor</remarks>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        HBITMAP CreateBitmap(
        int nWidth, // bitmap width, in pixels
        int nHeight, // bitmap height, in pixels
        UINT cPlanes, // number of color planes
        UINT cBitsPerPel, // number of bits to identify color
        LPVOID lpvBits // color data array
        );

        //TODO: CreateBitmapIndirect
        /*
        /// <summary>
        /// Creates a bitmap. 
        /// </summary>
        /// <param name="lpbm"></param>
        /// <returns></returns>
        HBITMAP CreateBitmapIndirect(
        LPBITMAP lpbm // bitmap data
        );
        */

        /// <summary>
        /// Creates a bitmap compatible with a device. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="nWidth"></param>
        /// <param name="nHeight"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        HBITMAP CreateCompatibleBitmap(
        HDC hdc, // handle to DC
        int nWidth, // width of bitmap, in pixels
        int nHeight // height of bitmap, in pixels
        );


        /// <summary>
        /// Creates a device-dependent bitmap (DDB) from a DIB. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="bmih"></param>
        /// <param name="fdwInit"></param>
        /// <param name="lpbInit"></param>
        /// <param name="bmi"></param>
        /// <param name="fuUsage"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern /// 
        HBITMAP CreateDIBitmap(
        HDC hdc, // handle to DC
        ref BITMAPINFOHEADER bmih, // bitmap data
        DWORD fdwInit, // initialization option
        LPVOID lpbInit, // initialization data
        ref BITMAPINFO bmi, // color-format data
        UINT fuUsage // color-data usage
        );


        //TODO: CreateDIBSection
        /*
        /// <summary>
        /// Creates a DIB that applications can write to directly. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="BITMAPINFO"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern 
        HBITMAP CreateDIBSection(
        HDC hdc, // handle to DC
        CONST BITMAPINFO *pbmi, // bitmap data
        UINT iUsage, // data type indicator
        VOID **ppvBits, // bit values
        HANDLE hSection, // handle to file mapping object
        DWORD dwOffset // offset to bitmap bit values
        );
        */



        /// <summary>
        /// Fills an area of the display surface with the current brush. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="nXStart"></param>
        /// <param name="nYStart"></param>
        /// <param name="crColor"></param>
        /// <param name="fuFillType"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        BOOL ExtFloodFill(
        HDC hdc, // handle to DC
        int nXStart, // starting x-coordinate 
        int nYStart, // starting y-coordinate 
        COLORREF crColor, // fill color
        UINT fuFillType // fill type
        );


        /// <summary>
        /// Gets the dimensions of a bitmap. 
        /// </summary>
        /// <param name="hBitmap"></param>
        /// <param name="Dimension"></param>
        /// <returns></returns>
        /// <remarks>System.Drawing.Bitmap.Size</remarks>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        BOOL GetBitmapDimensionEx(
        HBITMAP hBitmap, // handle to bitmap
        ref Int32 Dimension // dimensions
        );

        /*
        //TODO: GetDIBColorTable
        /// <summary>
        /// Retrieves RGB color values from a DIB section bitmap. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="uStartIndex"></param>
        /// <param name="cEntries"></param>
        /// <param name="pColors"></param>
        /// <returns></returns>
        /// <remarks>System.Drawing.Bitmap.Palette</remarks>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern 
        UINT GetDIBColorTable(
        HDC hdc, // handle to DC
        UINT uStartIndex, // color table index of first entry
        UINT cEntries, // number of entries to retrieve
        RGBQUAD* pColors // array of color table entries
        );
        */


        /// <summary>
        /// Copies a bitmap into a buffer. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="hbmp"></param>
        /// <param name="uStartScan"></param>
        /// <param name="cScanLines"></param>
        /// <param name="lpvBits"></param>
        /// <param name="bi"></param>
        /// <param name="uUsage"></param>
        /// <returns></returns>
        /// <remarks>System.Drawing.Bitmap.LockBits</remarks>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        int GetDIBits(
        HDC hdc, // handle to DC
        HBITMAP hbmp, // handle to bitmap
        UINT uStartScan, // first scan line to set
        UINT cScanLines, // number of scan lines to copy
        LPVOID lpvBits, // array for bitmap bits
        ref BITMAPINFO bi, // bitmap data buffer
        UINT uUsage // RGB or palette index
        );


        /// <summary>
        /// Gets the RGB color value of the pixel at a given coordinate. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="nXPos"></param>
        /// <param name="nYPos"></param>
        /// <returns></returns>
        /// <remarks>System.Drawing.Bitmap.GetPixel</remarks>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        COLORREF GetPixel(
        HDC hdc, // handle to DC
        int nXPos, // x-coordinate of pixel
        int nYPos // y-coordinate of pixel
        );


        /// <summary>
        /// Gets the current stretching mode.
        /// </summary>
        /// <param name="hdc"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        int GetStretchBltMode(
        HDC hdc // handle to DC
        );

        /*
        //TODO: GradientFill
        /// <summary>
        /// Fills rectangle and triangle structures. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="pVertex"></param>
        /// <param name="dwNumVertex"></param>
        /// <param name="pMesh"></param>
        /// <param name="dwNumMesh"></param>
        /// <param name="dwMode"></param>
        /// <returns></returns>
        /// <remarks>System.Drawing.Graphics.FillRectangle(Drawing2D.LinearGradiantBrush, Rectangle)</remarks>
        BOOL GradientFill(
        HDC hdc, // handle to DC
        PTRIVERTEX pVertex, // array of vertices
        ULONG dwNumVertex, // number of vertices
        PVOID pMesh, // array of gradients
        ULONG dwNumMesh, // size of gradient array
        ULONG dwMode // gradient fill mode
        ); 
        */

        /// <summary>
        /// Loads a bitmap from a module's executable file. 
        /// </summary>
        /// <param name="hInstance"></param>
        /// <param name="lpBitmapName"></param>
        /// <returns></returns>
        /// <remarks>
        /// hInstance = System.Diagnostics.Process.GetCurrentProcess().Handle;
        /// 
        /// System.Drawing.Bitmap.Bitmap(Type, String)
        /// </remarks>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        HBITMAP LoadBitmap(
        HINSTANCE hInstance, // handle to application instance
        LPCTSTR lpBitmapName // name of bitmap resource
        );


        /// <summary>
        /// Combines the color data in the source and destination bitmaps. 
        /// </summary>
        /// <param name="hdcDest"></param>
        /// <param name="nXDest"></param>
        /// <param name="nYDest"></param>
        /// <param name="nWidth"></param>
        /// <param name="nHeight"></param>
        /// <param name="hdcSrc"></param>
        /// <param name="nXSrc"></param>
        /// <param name="nYSrc"></param>
        /// <param name="hbmMask"></param>
        /// <param name="xMask"></param>
        /// <param name="yMask"></param>
        /// <param name="dwRop"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        BOOL MaskBlt(
        HDC hdcDest, // handle to destination DC
        int nXDest, // x-coord of destination upper-left corner
        int nYDest, // y-coord of destination upper-left corner 
        int nWidth, // width of source and destination
        int nHeight, // height of source and destination
        HDC hdcSrc, // handle to source DC
        int nXSrc, // x-coord of upper-left corner of source
        int nYSrc, // y-coord of upper-left corner of source
        HBITMAP hbmMask, // handle to monochrome bit mask
        int xMask, // horizontal offset into mask bitmap
        int yMask, // vertical offset into mask bitmap
        DWORD dwRop // raster operation code
        );

        //TODO: PlgBlt
        /*
        /// <summary>
        /// Performs a bit-block transfer. 
        /// </summary>
        /// <param name="hdcDest"></param>
        /// <param name="POINT"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern 
        BOOL PlgBlt(
        HDC hdcDest, // handle to destination DC
        CONST POINT *lpPoint, // destination vertices
        HDC hdcSrc, // handle to source DC
        int nXSrc, // x-coord of source upper-left corner
        int nYSrc, // y-coord of source upper-left corner
        int nWidth, // width of source rectangle
        int nHeight, // height of source rectangle
        HBITMAP hbmMask, // handle to bitmask
        int xMask, // x-coord of bitmask upper-left corner
        int yMask // y-coord of bitmask upper-left corner
        );
        */

        /// <summary>
        /// Sets the preferred dimensions to a bitmap. 
        /// </summary>
        /// <param name="hBitmap"></param>
        /// <param name="nWidth"></param>
        /// <param name="nHeight"></param>
        /// <param name="lpSize"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        BOOL SetBitmapDimensionEx(
        HBITMAP hBitmap, // handle to bitmap
        int nWidth, // bitmap width in .01-mm units
        int nHeight, // bitmap height in .01-mm units
        ref Int32 lpSize // original dimensions
        );

        //TODO: SetDIBColorTable
        /*
        /// <summary>
        /// Sets RGB values in a DIB. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="uStartIndex"></param>
        /// <param name="cEntries"></param>
        /// <param name="RGBQUAD"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern 
        UINT SetDIBColorTable(
        HDC hdc, // handle to DC
        UINT uStartIndex, // color table index of first entry
        UINT cEntries, // number of color table entries
        CONST RGBQUAD *pColors // array of color table entries
        );
        */


        /// <summary>
        /// Sets the pixels in a bitmap using color data from a DIB. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="hbmp"></param>
        /// <param name="uStartScan"></param>
        /// <param name="cScanLines"></param>
        /// <param name="lpvBits"></param>
        /// <param name="lpbmi"></param>
        /// <param name="fuColorUse"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        int SetDIBits(
        HDC hdc, // handle to DC
        HBITMAP hbmp, // handle to bitmap
        UINT uStartScan, // starting scan line
        UINT cScanLines, // number of scan lines
        LPVOID lpvBits, // array of bitmap bits
        ref BITMAPINFO lpbmi, // bitmap data
        UINT fuColorUse // type of color indexes to use
        );


        /// <summary>
        /// Sets the pixels in a rectangle using color data from a DIB. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="XDest"></param>
        /// <param name="YDest"></param>
        /// <param name="dwWidth"></param>
        /// <param name="dwHeight"></param>
        /// <param name="XSrc"></param>
        /// <param name="YSrc"></param>
        /// <param name="uStartScan"></param>
        /// <param name="cScanLines"></param>
        /// <param name="lpvBits"></param>
        /// <param name="bmi"></param>
        /// <param name="fuColorUse"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        int SetDIBitsToDevice(
        HDC hdc, // handle to DC
        int XDest, // x-coord of destination upper-left corner
        int YDest, // y-coord of destination upper-left corner 
        DWORD dwWidth, // source rectangle width
        DWORD dwHeight, // source rectangle height
        int XSrc, // x-coord of source lower-left corner
        int YSrc, // y-coord of source lower-left corner
        UINT uStartScan, // first scan line in array
        UINT cScanLines, // number of scan lines
        LPVOID lpvBits, // array of DIB bits
        //ref BITMAPINFO bmi, // bitmap information
        LPVOID bmi,
        UINT fuColorUse // RGB or palette indexes
        );

        /// <summary>
        /// Sets the color for a pixel. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <param name="crColor"></param>
        /// <returns></returns>
        /// <remarks>System.Drawing.Bitmap.SetPixel</remarks>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        COLORREF SetPixel(
        HDC hdc, // handle to DC
        int X, // x-coordinate of pixel
        int Y, // y-coordinate of pixel
        COLORREF crColor // pixel color
        );


        /// <summary>
        /// Sets a pixel to the best approximation of a color.
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <param name="crColor"></param>
        /// <returns></returns>
        /// <remarks>System.Drawing.Bitmap.SetPixel(…, Graphics.GetNearestColor(Color))</remarks>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        BOOL SetPixelV(
        HDC hdc, // handle to device context
        int X, // x-coordinate of pixel
        int Y, // y-coordinate of pixel
        COLORREF crColor // new pixel color
        );


        /// <summary>
        /// Sets the bitmap stretching mode. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="iStretchMode"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        int SetStretchBltMode(
        HDC hdc, // handle to DC
        int iStretchMode // bitmap stretching mode
        );


        /// <summary>
        /// Copies a bitmap and stretches or compresses it. 
        /// </summary>
        /// <param name="hdcDest"></param>
        /// <param name="nXOriginDest"></param>
        /// <param name="nYOriginDest"></param>
        /// <param name="nWidthDest"></param>
        /// <param name="nHeightDest"></param>
        /// <param name="hdcSrc"></param>
        /// <param name="nXOriginSrc"></param>
        /// <param name="nYOriginSrc"></param>
        /// <param name="nWidthSrc"></param>
        /// <param name="nHeightSrc"></param>
        /// <param name="dwRop"></param>
        /// <returns></returns>
        /// <remarks>System.Drawing.Graphics.DrawImage</remarks>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        BOOL StretchBlt(
        HDC hdcDest, // handle to destination DC
        int nXOriginDest, // x-coord of destination upper-left corner
        int nYOriginDest, // y-coord of destination upper-left corner
        int nWidthDest, // width of destination rectangle
        int nHeightDest, // height of destination rectangle
        HDC hdcSrc, // handle to source DC
        int nXOriginSrc, // x-coord of source upper-left corner
        int nYOriginSrc, // y-coord of source upper-left corner
        int nWidthSrc, // width of source rectangle
        int nHeightSrc, // height of source rectangle
        DWORD dwRop // raster operation code
        );


        /// <summary>
        /// Copies the color data in a DIB. 
        /// </summary>
        /// <param name="hdc"></param>
        /// <param name="XDest"></param>
        /// <param name="YDest"></param>
        /// <param name="nDestWidth"></param>
        /// <param name="nDestHeight"></param>
        /// <param name="XSrc"></param>
        /// <param name="YSrc"></param>
        /// <param name="nSrcWidth"></param>
        /// <param name="nSrcHeight"></param>
        /// <param name="lpBits"></param>
        /// <param name="lpBitsInfo"></param>
        /// <param name="iUsage"></param>
        /// <param name="dwRop"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        int StretchDIBits(
        HDC hdc, // handle to DC
        int XDest, // x-coord of destination upper-left corner
        int YDest, // y-coord of destination upper-left corner
        uint nDestWidth, // width of destination rectangle
        uint nDestHeight, // height of destination rectangle
        int XSrc, // x-coord of source upper-left corner
        int YSrc, // y-coord of source upper-left corner
        uint nSrcWidth, // width of source rectangle
        uint nSrcHeight, // height of source rectangle
        LPVOID lpBits, // bitmap bits
        //ref BITMAPINFO lpBitsInfo, // bitmap data
        LPVOID lpBitsInfo,
        UINT iUsage, // usage options
        DWORD dwRop // raster operation code
        );


        /// <summary>
        /// Performs a bit-block transfer of color data. 
        /// </summary>
        /// <param name="hdcDest"></param>
        /// <param name="nXOriginDest"></param>
        /// <param name="nYOriginDest"></param>
        /// <param name="nWidthDest"></param>
        /// <param name="hHeightDest"></param>
        /// <param name="hdcSrc"></param>
        /// <param name="nXOriginSrc"></param>
        /// <param name="nYOriginSrc"></param>
        /// <param name="nWidthSrc"></param>
        /// <param name="nHeightSrc"></param>
        /// <param name="crTransparent"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern
        BOOL TransparentBlt(
        HDC hdcDest, // handle to destination DC
        int nXOriginDest, // x-coord of destination upper-left corner
        int nYOriginDest, // y-coord of destination upper-left corner
        int nWidthDest, // width of destination rectangle
        int hHeightDest, // height of destination rectangle
        HDC hdcSrc, // handle to source DC
        int nXOriginSrc, // x-coord of source upper-left corner
        int nYOriginSrc, // y-coord of source upper-left corner
        int nWidthSrc, // width of source rectangle
        int nHeightSrc, // height of source rectangle
        UINT crTransparent // color to make transparent
        );


        #endregion Bitmaps
    }
}
